home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume91 / utilitys / bmake_06 / part02 < prev    next >
Encoding:
Internet Message Format  |  1991-07-04  |  54.6 KB

  1. Path: news.larc.nasa.gov!amiga-request
  2. From: amiga-request@ab20.larc.nasa.gov (Amiga Sources/Binaries Moderator)
  3. Subject: v91i124: bmake 0.6 - automate recompiling multiple source files, Part02/03
  4. Reply-To: ENG  BENNY <engb@ecf.toronto.edu>
  5. Newsgroups: comp.sources.amiga
  6. Message-ID: <comp.sources.amiga.v91i124@ab20.larc.nasa.gov>
  7. References: <comp.sources.amiga.v91i123@ab20.larc.nasa.gov>
  8. Date: 04 Jul 91 16:38:43 GMT
  9. Approved: tadguy@uunet.UU.NET (Tad Guy)
  10. X-Mail-Submissions-To: amiga@uunet.uu.net
  11. X-Post-Discussions-To: comp.sys.amiga.misc
  12.  
  13. Submitted-by: ENG  BENNY <engb@ecf.toronto.edu>
  14. Posting-number: Volume 91, Issue 124
  15. Archive-name: utilities/bmake-0.6/part02
  16.  
  17. #!/bin/sh
  18. # This is a shell archive.  Remove anything before this line, then unpack
  19. # it by saving it into a file and typing "sh file".  To overwrite existing
  20. # files, type "sh file -c".  You can also feed this as standard input via
  21. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  22. # will see the following message at the end:
  23. #        "End of archive 2 (of 3)."
  24. # Contents:  copying expand.c fncall.c input.c make.c read.c
  25. # Wrapped by tadguy@ab20 on Thu Jul  4 12:38:41 1991
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'copying' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'copying'\"
  29. else
  30. echo shar: Extracting \"'copying'\" \(12488 characters\)
  31. sed "s/^X//" >'copying' <<'END_OF_FILE'
  32. X
  33. X            GNU GENERAL PUBLIC LICENSE
  34. X             Version 1, February 1989
  35. X
  36. X Copyright (C) 1989 Free Software Foundation, Inc.
  37. X                    675 Mass Ave, Cambridge, MA 02139, USA
  38. X Everyone is permitted to copy and distribute verbatim copies
  39. X of this license document, but changing it is not allowed.
  40. X
  41. X                Preamble
  42. X
  43. X  The license agreements of most software companies try to keep users
  44. Xat the mercy of those companies.  By contrast, our General Public
  45. XLicense is intended to guarantee your freedom to share and change free
  46. Xsoftware--to make sure the software is free for all its users.  The
  47. XGeneral Public License applies to the Free Software Foundation's
  48. Xsoftware and to any other program whose authors commit to using it.
  49. XYou can use it for your programs, too.
  50. X
  51. X  When we speak of free software, we are referring to freedom, not
  52. Xprice.  Specifically, the General Public License is designed to make
  53. Xsure that you have the freedom to give away or sell copies of free
  54. Xsoftware, that you receive source code or can get it if you want it,
  55. Xthat you can change the software or use pieces of it in new free
  56. Xprograms; and that you know you can do these things.
  57. X
  58. X  To protect your rights, we need to make restrictions that forbid
  59. Xanyone to deny you these rights or to ask you to surrender the rights.
  60. XThese restrictions translate to certain responsibilities for you if you
  61. Xdistribute copies of the software, or if you modify it.
  62. X
  63. X  For example, if you distribute copies of a such a program, whether
  64. Xgratis or for a fee, you must give the recipients all the rights that
  65. Xyou have.  You must make sure that they, too, receive or can get the
  66. Xsource code.  And you must tell them their rights.
  67. X
  68. X  We protect your rights with two steps: (1) copyright the software, and
  69. X(2) offer you this license which gives you legal permission to copy,
  70. Xdistribute and/or modify the software.
  71. X
  72. X  Also, for each author's protection and ours, we want to make certain
  73. Xthat everyone understands that there is no warranty for this free
  74. Xsoftware.  If the software is modified by someone else and passed on, we
  75. Xwant its recipients to know that what they have is not the original, so
  76. Xthat any problems introduced by others will not reflect on the original
  77. Xauthors' reputations.
  78. X
  79. X  The precise terms and conditions for copying, distribution and
  80. Xmodification follow.
  81. X
  82. X            GNU GENERAL PUBLIC LICENSE
  83. X   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
  84. X
  85. X  0. This License Agreement applies to any program or other work which
  86. Xcontains a notice placed by the copyright holder saying it may be
  87. Xdistributed under the terms of this General Public License.  The
  88. X"Program", below, refers to any such program or work, and a "work based
  89. Xon the Program" means either the Program or any work containing the
  90. XProgram or a portion of it, either verbatim or with modifications.  Each
  91. Xlicensee is addressed as "you".
  92. X
  93. X  1. You may copy and distribute verbatim copies of the Program's source
  94. Xcode as you receive it, in any medium, provided that you conspicuously and
  95. Xappropriately publish on each copy an appropriate copyright notice and
  96. Xdisclaimer of warranty; keep intact all the notices that refer to this
  97. XGeneral Public License and to the absence of any warranty; and give any
  98. Xother recipients of the Program a copy of this General Public License
  99. Xalong with the Program.  You may charge a fee for the physical act of
  100. Xtransferring a copy.
  101. X
  102. X  2. You may modify your copy or copies of the Program or any portion of
  103. Xit, and copy and distribute such modifications under the terms of Paragraph
  104. X1 above, provided that you also do the following:
  105. X
  106. X    a) cause the modified files to carry prominent notices stating that
  107. X    you changed the files and the date of any change; and
  108. X
  109. X    b) cause the whole of any work that you distribute or publish, that
  110. X    in whole or in part contains the Program or any part thereof, either
  111. X    with or without modifications, to be licensed at no charge to all
  112. X    third parties under the terms of this General Public License (except
  113. X    that you may choose to grant warranty protection to some or all
  114. X    third parties, at your option).
  115. X
  116. X    c) If the modified program normally reads commands interactively when
  117. X    run, you must cause it, when started running for such interactive use
  118. X    in the simplest and most usual way, to print or display an
  119. X    announcement including an appropriate copyright notice and a notice
  120. X    that there is no warranty (or else, saying that you provide a
  121. X    warranty) and that users may redistribute the program under these
  122. X    conditions, and telling the user how to view a copy of this General
  123. X    Public License.
  124. X
  125. X    d) You may charge a fee for the physical act of transferring a
  126. X    copy, and you may at your option offer warranty protection in
  127. X    exchange for a fee.
  128. X
  129. XMere aggregation of another independent work with the Program (or its
  130. Xderivative) on a volume of a storage or distribution medium does not bring
  131. Xthe other work under the scope of these terms.
  132. X
  133. X  3. You may copy and distribute the Program (or a portion or derivative of
  134. Xit, under Paragraph 2) in object code or executable form under the terms of
  135. XParagraphs 1 and 2 above provided that you also do one of the following:
  136. X
  137. X    a) accompany it with the complete corresponding machine-readable
  138. X    source code, which must be distributed under the terms of
  139. X    Paragraphs 1 and 2 above; or,
  140. X
  141. X    b) accompany it with a written offer, valid for at least three
  142. X    years, to give any third party free (except for a nominal charge
  143. X    for the cost of distribution) a complete machine-readable copy of the
  144. X    corresponding source code, to be distributed under the terms of
  145. X    Paragraphs 1 and 2 above; or,
  146. X
  147. X    c) accompany it with the information you received as to where the
  148. X    corresponding source code may be obtained.  (This alternative is
  149. X    allowed only for noncommercial distribution and only if you
  150. X    received the program in object code or executable form alone.)
  151. X
  152. XSource code for a work means the preferred form of the work for making
  153. Xmodifications to it.  For an executable file, complete source code means
  154. Xall the source code for all modules it contains; but, as a special
  155. Xexception, it need not include source code for modules which are standard
  156. Xlibraries that accompany the operating system on which the executable
  157. Xfile runs, or for standard header files or definitions files that
  158. Xaccompany that operating system.
  159. X
  160. X  4. You may not copy, modify, sublicense, distribute or transfer the
  161. XProgram except as expressly provided under this General Public License.
  162. XAny attempt otherwise to copy, modify, sublicense, distribute or transfer
  163. Xthe Program is void, and will automatically terminate your rights to use
  164. Xthe Program under this License.  However, parties who have received
  165. Xcopies, or rights to use copies, from you under this General Public
  166. XLicense will not have their licenses terminated so long as such parties
  167. Xremain in full compliance.
  168. X
  169. X  5. By copying, distributing or modifying the Program (or any work based
  170. Xon the Program) you indicate your acceptance of this license to do so,
  171. Xand all its terms and conditions.
  172. X
  173. X  6. Each time you redistribute the Program (or any work based on the
  174. XProgram), the recipient automatically receives a license from the original
  175. Xlicensor to copy, distribute or modify the Program subject to these
  176. Xterms and conditions.  You may not impose any further restrictions on the
  177. Xrecipients' exercise of the rights granted herein.
  178. X
  179. X  7. The Free Software Foundation may publish revised and/or new versions
  180. Xof the General Public License from time to time.  Such new versions will
  181. Xbe similar in spirit to the present version, but may differ in detail to
  182. Xaddress new problems or concerns.
  183. X
  184. XEach version is given a distinguishing version number.  If the Program
  185. Xspecifies a version number of the license which applies to it and "any
  186. Xlater version", you have the option of following the terms and conditions
  187. Xeither of that version or of any later version published by the Free
  188. XSoftware Foundation.  If the Program does not specify a version number of
  189. Xthe license, you may choose any version ever published by the Free Software
  190. XFoundation.
  191. X
  192. X  8. If you wish to incorporate parts of the Program into other free
  193. Xprograms whose distribution conditions are different, write to the author
  194. Xto ask for permission.  For software which is copyrighted by the Free
  195. XSoftware Foundation, write to the Free Software Foundation; we sometimes
  196. Xmake exceptions for this.  Our decision will be guided by the two goals
  197. Xof preserving the free status of all derivatives of our free software and
  198. Xof promoting the sharing and reuse of software generally.
  199. X
  200. X                NO WARRANTY
  201. X
  202. X  9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
  203. XFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
  204. XOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
  205. XPROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
  206. XOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  207. XMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
  208. XTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
  209. XPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
  210. XREPAIR OR CORRECTION.
  211. X
  212. X  10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
  213. XWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
  214. XREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
  215. XINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
  216. XOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
  217. XTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
  218. XYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
  219. XPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
  220. XPOSSIBILITY OF SUCH DAMAGES.
  221. X
  222. X             END OF TERMS AND CONDITIONS
  223. X
  224. X    Appendix: How to Apply These Terms to Your New Programs
  225. X
  226. X  If you develop a new program, and you want it to be of the greatest
  227. Xpossible use to humanity, the best way to achieve this is to make it
  228. Xfree software which everyone can redistribute and change under these
  229. Xterms.
  230. X
  231. X  To do so, attach the following notices to the program.  It is safest to
  232. Xattach them to the start of each source file to most effectively convey
  233. Xthe exclusion of warranty; and each file should have at least the
  234. X"copyright" line and a pointer to where the full notice is found.
  235. X
  236. X    <one line to give the program's name and a brief idea of what it does.>
  237. X    Copyright (C) 19yy  <name of author>
  238. X
  239. X    This program is free software; you can redistribute it and/or modify
  240. X    it under the terms of the GNU General Public License as published by
  241. X    the Free Software Foundation; either version 1, or (at your option)
  242. X    any later version.
  243. X
  244. X    This program is distributed in the hope that it will be useful,
  245. X    but WITHOUT ANY WARRANTY; without even the implied warranty of
  246. X    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  247. X    GNU General Public License for more details.
  248. X
  249. X    You should have received a copy of the GNU General Public License
  250. X    along with this program; if not, write to the Free Software
  251. X    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  252. X
  253. XAlso add information on how to contact you by electronic and paper mail.
  254. X
  255. XIf the program is interactive, make it output a short notice like this
  256. Xwhen it starts in an interactive mode:
  257. X
  258. X    Gnomovision version 69, Copyright (C) 19xx name of author
  259. X    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
  260. X    This is free software, and you are welcome to redistribute it
  261. X    under certain conditions; type `show c' for details.
  262. X
  263. XThe hypothetical commands `show w' and `show c' should show the
  264. Xappropriate parts of the General Public License.  Of course, the
  265. Xcommands you use may be called something other than `show w' and `show
  266. Xc'; they could even be mouse-clicks or menu items--whatever suits your
  267. Xprogram.
  268. X
  269. XYou should also get your employer (if you work as a programmer) or your
  270. Xschool, if any, to sign a "copyright disclaimer" for the program, if
  271. Xnecessary.  Here a sample; alter the names:
  272. X
  273. X  Yoyodyne, Inc., hereby disclaims all copyright interest in the
  274. X  program `Gnomovision' (a program to direct compilers to make passes
  275. X  at assemblers) written by James Hacker.
  276. X
  277. X  <signature of Ty Coon>, 1 April 1989
  278. X  Ty Coon, President of Vice
  279. X
  280. XThat's all there is to it!
  281. END_OF_FILE
  282. if test 12488 -ne `wc -c <'copying'`; then
  283.     echo shar: \"'copying'\" unpacked with wrong size!
  284. fi
  285. # end of 'copying'
  286. fi
  287. if test -f 'expand.c' -a "${1}" != "-c" ; then 
  288.   echo shar: Will not clobber existing file \"'expand.c'\"
  289. else
  290. echo shar: Extracting \"'expand.c'\" \(6120 characters\)
  291. sed "s/^X//" >'expand.c' <<'END_OF_FILE'
  292. X/*    expand.c
  293. X *  (c) Copyright 1991 by Ben Eng, All Rights Reserved
  294. X *
  295. X *    macro expansion
  296. X */
  297. X
  298. X#include <clib/exec_protos.h>
  299. X
  300. X#include <ctype.h>
  301. X
  302. X#include "make.h"
  303. X#include "depend.h"
  304. X
  305. Xstatic int expand_macros2( char *dest, char *src, int maxlen );
  306. Xstatic int expand_macros3( char *src, int maxlen );
  307. X
  308. X/*    define the criterion for detecting infinitely recursive
  309. X *    macro expansions
  310. X */
  311. Xstatic int expand_level = 0;
  312. X#define MAX_RECURSION    32
  313. X#define MAX_ITERATION    256
  314. X
  315. X/*    returns 0 if a function was completed successfully
  316. X */
  317. Xstatic struct macro *
  318. Xexpand_fncall( char *src, int maxlen )
  319. X{
  320. X    static struct macro *fnmac = NULL;
  321. X    struct fncall *fc;
  322. X    char fn[ 40 ], *next = src;
  323. X    int addlen;
  324. X
  325. X    if( fnmac) {
  326. X        if( fnmac->expansion ) {
  327. X            free( fnmac->expansion );
  328. X            fnmac->expansion = NULL;
  329. X        }
  330. X    }
  331. X    else if( fnmac = new_macro( NULL, NULL ))
  332. X        fnmac->flags |= MF_SIMPLE;
  333. X    else return( NULL );
  334. X
  335. X    next = parse_str( fn, next, sizeof(fn));
  336. X    if( fc = find_fncall( fn )) {
  337. X        if( (*fc->call)( fnmac, next )) {
  338. X            logprintf( "function call %s returned ERROR\n", fc->name );
  339. X            return( NULL );
  340. X        }
  341. X        fnmac->flags |= MF_SIMPLE;
  342. X        return( fnmac );
  343. X    }
  344. X    return( NULL );
  345. X}
  346. X
  347. X/*    expand a macro reference with only a single $(x) instance
  348. X *    handles recursive expansion
  349. X */
  350. Xstatic int
  351. Xexpand_macros3( char *src, int maxlen )
  352. X{
  353. X    char *dest = NULL;
  354. X    char *macroname = NULL;
  355. X    char *dollar;
  356. X
  357. X    dollar = strchr( src, '$' );
  358. X    if( dollar ) {
  359. X        struct macro *mac = NULL;
  360. X        char *out, *next;
  361. X         int outlen = 0;
  362. X        char delimchar = (char)0;
  363. X
  364. X        debugprintf( 6,( "expand_macros3(%s,%d)\n", src, maxlen ));
  365. X
  366. X        /* could get away with only allocating maxlen to save memory */
  367. X        macroname = (char *)malloc( Param.MaxLine );
  368. X        dest = (char *)calloc( Param.MaxLine, 1 );
  369. X        if( !macroname || !dest ) goto death;
  370. X
  371. X        out = dest;
  372. X
  373. X        memset( macroname, 0, Param.MaxLine);
  374. X        for( next = src; next < dollar && outlen < maxlen; outlen++ )
  375. X            *out++ = *next++;
  376. X
  377. X        next = dollar + 1;
  378. X        if( outlen >= maxlen ) goto death;
  379. X
  380. X        if( *next == '(' ) delimchar = ')';
  381. X        else if( *next == '{' ) delimchar = '}';
  382. X
  383. X        if( delimchar ) { /* multi letter variable name */
  384. X            char *n;
  385. X            int i = 0;
  386. X
  387. X            for( n = ++next; *n && i < Param.MaxLine-1; n++ ) {
  388. X                if( *n == delimchar ) break;
  389. X                macroname[ i++ ] = *n;
  390. X            }
  391. X            if( *n != delimchar ) {
  392. X                logprintf( "macro name is too long [%s]\n", macroname );
  393. X                logprintf( "macro names are limited to %d\n",
  394. X                    Param.MaxLine );
  395. X                goto death;
  396. X            }
  397. X            next = n + 1;
  398. X        }
  399. X        else { /* single letter variable name */
  400. X            macroname[ 0 ] = *next++; /* advance past the macroname */
  401. X        }
  402. X
  403. X        if( mac = expand_fncall( macroname, maxlen - outlen )) {
  404. X            debugprintf( 4,( "fncall macro [%s] = %s\n", macroname,
  405. X                mac->expansion ));
  406. X        }
  407. X        else if( !(mac = find_macro( macroname )) && getenv( macroname )) {
  408. X            /* use getenv() to assign a simple macro */
  409. X            debugprintf( 4,( "getenv macro [%s]\n", macroname ));
  410. X            if( mac = set_macro( macroname, getenv( macroname ))) {
  411. X                mac->flags |= MF_SIMPLE;
  412. X            }
  413. X        }
  414. X        if( mac ) {
  415. X            int cdrlen = maxlen - outlen;
  416. X            if( mac->flags & MF_EXPANDED ) {
  417. X                logprintf( "infinitely recursive macro expansion: %s\n",
  418. X                    macroname );
  419. X                goto death;
  420. X            }
  421. X            memset( out, 0, cdrlen );
  422. X            if( mac->expansion) strncpy( out, mac->expansion, cdrlen );
  423. X            cdrlen -= strlen( out );
  424. X            if( cdrlen < 0 ) {
  425. X                logprintf( "expand_macros3 ERROR: cdrlen is %d\n",
  426. X                    cdrlen );
  427. X                goto death;
  428. X            }
  429. X            strncpy( out + strlen(out), next, cdrlen );
  430. X            if( !(mac->flags & MF_SIMPLE )) {
  431. X                /* recursively expand nested macro expansion */
  432. X                mac->flags |= MF_EXPANDED;
  433. X                if( expand_macros2( out, out, cdrlen )) goto death;
  434. X                mac->flags &= ~MF_EXPANDED;
  435. X            }
  436. X        }
  437. X        else {
  438. X            logprintf( "WARNING:  unknown macro [%s]\n", macroname );
  439. X            strncpy( out + strlen(out), next, maxlen - outlen );
  440. X        }
  441. X        /* for next macro occurrence on the line */
  442. X        outlen = min( strlen( dest ), maxlen );
  443. X
  444. X        debugprintf( 6,( "expand_macros3 returns [%s] %d\n", dest, outlen ));
  445. X
  446. X        strncpy( src, dest, outlen ); /* copy the expansion back */
  447. X        src[ outlen  ] = (char)0;
  448. X        free( macroname ); macroname = NULL;
  449. X        free( dest ); dest = NULL;
  450. X    } /* dollar */
  451. X
  452. X    return( 0 );
  453. Xdeath:
  454. X    if( macroname ) free( macroname );
  455. X    if( dest ) free( dest );
  456. X    return( 1 );
  457. X}
  458. X
  459. X/*    find the rightmost occurrence of the character tok
  460. X *    starting at prev in the string
  461. X */
  462. Xstatic char *
  463. Xstrrlchr( char *string, char tok, char *prev )
  464. X{
  465. X    while( prev >= string ) {
  466. X        if( *prev == tok ) return( prev );
  467. X        prev--;
  468. X    }
  469. X    return( NULL );
  470. X}
  471. X
  472. X/*    expand a line with multiple $(x) instances
  473. X *    expand right to left to avoid recursion
  474. X */
  475. Xstatic int
  476. Xexpand_macros2( char *dest, char *src, int maxlen )
  477. X{
  478. X    char *dollar, *prev;
  479. X    int iteration = 0;
  480. X
  481. X    /* increment the recursion level counter */
  482. X    if( ++expand_level > MAX_RECURSION ){
  483. X        logprintf( "Infinite Macro expansion aborted at %d recursions\n",
  484. X            expand_level );
  485. X        return( 1 );
  486. X    }
  487. X    debugprintf( 6,( "expand_macros2(%s,%d)\n", src, maxlen ));
  488. X    if( src != dest ) strncpy( dest, src, maxlen );
  489. X    prev = dest + strlen(dest);
  490. X    while( dollar = strrlchr( dest, '$', prev )) {
  491. X        if( ++iteration > MAX_ITERATION ) {
  492. X            logprintf( "Infinite Macro expansion aborted at %d iterations\n",
  493. X                iteration );
  494. X            return( 1 );
  495. X        }
  496. X        if( dollar[-1] == '$' || dollar[-1] == '\\' ) {
  497. X            shift_string_left( dollar - 1, 1 );
  498. X            --dollar;
  499. X        }
  500. X        else if( expand_macros3( dollar, maxlen - (int)(dollar - dest) ))
  501. X            return( 1 );
  502. X        prev = dollar - 1;
  503. X    }
  504. X    debugprintf( 6,( "expand_macros2 returns [%s]\n", dest ));
  505. X    return( 0 );
  506. X}
  507. X
  508. X/*    to reset each variable's flags before expansion begins */
  509. Xstatic long
  510. Xreset_macroflag( struct macro *mac )
  511. X{
  512. X    mac->flags &= ~MF_EXPANDED;
  513. X    return( 0 );
  514. X}
  515. X
  516. X/*    top level macro expansion call
  517. X *    this is the entry point called from the outside
  518. X */
  519. Xint
  520. Xexpand_macros( char *dest, char *src, int maxlen )
  521. X{
  522. X    expand_level = 0;    /* reset the recursion level counter */
  523. X    memset( dest, 0, maxlen );
  524. X    for_list( &Global.macrolist, reset_macroflag );
  525. X    if( expand_macros2( dest, src, maxlen - 1 )) {
  526. X        logprintf( "Error expanding $(%s)\n", src );
  527. X        return( 1 );
  528. X    }
  529. X
  530. X    debugprintf( 3,( "expand_macros [%s] to [%s]\n", src, dest ));
  531. X    return( 0 );
  532. X}
  533. END_OF_FILE
  534. if test 6120 -ne `wc -c <'expand.c'`; then
  535.     echo shar: \"'expand.c'\" unpacked with wrong size!
  536. fi
  537. # end of 'expand.c'
  538. fi
  539. if test -f 'fncall.c' -a "${1}" != "-c" ; then 
  540.   echo shar: Will not clobber existing file \"'fncall.c'\"
  541. else
  542. echo shar: Extracting \"'fncall.c'\" \(10300 characters\)
  543. sed "s/^X//" >'fncall.c' <<'END_OF_FILE'
  544. X/*    fncall.c
  545. X *  (c) Copyright 1991 by Ben Eng, All Rights Reserved
  546. X *
  547. X */
  548. X
  549. X#include <clib/exec_protos.h>
  550. X
  551. X#include <ctype.h>
  552. X#include <scdir.h>
  553. X
  554. X#include "make.h"
  555. X#include "depend.h"
  556. X
  557. X#if FNCALLS
  558. X
  559. X/*    pattern matching routine */
  560. Xint
  561. Xismatch( char *pat, char *text )
  562. X{
  563. X    char *wild;
  564. X    int len;
  565. X
  566. X    debugprintf( 7, ( "ismatch(%s,%s)\n", pat, text ));
  567. X
  568. X    wild = find_token( pat, '%' );
  569. X
  570. X    if( !wild) return( strcmp( pat, text ) ? 0 : 1 );
  571. X
  572. X    /* the length of the part of pat before the % */
  573. X    len = (int)(wild - pat);
  574. X
  575. X    if( len && strncmp( pat, text, len )) return( 0 ); /* no match */
  576. X
  577. X    /* the length of the part of pat after the % */
  578. X    len = (int)(pat + strlen(pat) - wild - 1);
  579. X    if( len && strncmp( wild + 1, text + strlen(text) - len, len ))
  580. X            return( 0 ); /* no match */
  581. X
  582. X    return( 1 ); /* match */
  583. X}
  584. X
  585. X/*    function calls (mac, string)
  586. X *
  587. X *    The string parameter is the rest of the arguments passed to the
  588. X *    function call.  string is modifiable in fncalls because it is
  589. X *    actually contained within the macroname array[] which isn't
  590. X *    really used again after the fncall returns.
  591. X *
  592. X *    returns 0 if successful, 1 if error
  593. X *    with side effect:  mac->expansion = strdup( result_string );
  594. X *
  595. X */
  596. X
  597. Xstatic char argument_missing[] = "argument missing: %s %s\n";
  598. Xstatic char error_no_memory[] = "error:  no memory\n";
  599. X
  600. Xstatic int
  601. Xfn_basename( struct macro *mac, char *string )
  602. X{
  603. X    char *filelist = NULL;
  604. X    char *out, *text, *cptr;
  605. X    int len = 0;
  606. X    char word[ MAXPATHNAME ];
  607. X
  608. X    filelist = (char *)calloc( Param.MaxLine, 1 );
  609. X    if( !filelist ) {
  610. X        logfile( error_no_memory );
  611. X        return( 1 );
  612. X    }
  613. X    
  614. X    out = filelist;
  615. X    text = string;
  616. X
  617. X    while( len < Param.MaxLine ) {
  618. X        text = parse_str( word, text, sizeof(word));
  619. X        if( !*word ) break; /* no more words in text */
  620. X        if( (cptr = strrchr( word, '.' )) && ( basename(word) <= cptr )) {
  621. X            *cptr = (char)0; /* truncate the word at the `.' */
  622. X        }
  623. X        len += strlen( word );
  624. X        if( len < Param.MaxLine ) {
  625. X            if( out != filelist ) {
  626. X                *out++ = ' ';
  627. X                len++;
  628. X            }
  629. X            strcpy( out, word );
  630. X            out = filelist + len;
  631. X        }
  632. X    } /* while */
  633. X    *out = (char)0;
  634. X    if( len > 0 ) mac->expansion = strdup( filelist );
  635. X    free( filelist );
  636. X    return( 0 );
  637. X}
  638. X
  639. Xstatic int
  640. Xdo_addfix( struct macro *mac, char *string, int how_fix )
  641. X{
  642. X    char *filelist = NULL;
  643. X    char *suf, *str = string;
  644. X
  645. X    filelist = (char *)calloc( Param.MaxLine, 1 );
  646. X    if( !filelist ) {
  647. X        logfile( error_no_memory );
  648. X        return( 1 );
  649. X    }
  650. X
  651. X    while( isspace( *str )) str++;
  652. X    suf = str;
  653. X    while( *str && *str != ',' && str[-1] != '\\' ) str++;
  654. X    if( *suf != ',' && *str == ',' && str[-1] != '\\' ) {
  655. X        char *out, *text, *cptr;
  656. X        int suflen, len = 0;
  657. X        char word[ MAXPATHNAME ];
  658. X
  659. X        *str++ = (char)0; /* null terminate the suffix */
  660. X        suflen = strlen( suf );
  661. X        out = filelist;
  662. X        text = str;
  663. X
  664. X        while( len < Param.MaxLine ) {
  665. X            text = parse_str( word, text, sizeof(word));
  666. X            if( !*word ) break; /* no more words in text */
  667. X            if( (strlen( word )+suflen) < sizeof(word)) {
  668. X                if( how_fix ) /* append the suffix */
  669. X                    strcat( word, suf );
  670. X                else { /* prepend the prefix */
  671. X                    len += strlen( suf );
  672. X                    if( len + 1 < Param.MaxLine ) {
  673. X                        if( out != filelist ) {
  674. X                            *out++ = ' ';
  675. X                            len++;
  676. X                        }
  677. X                        strcpy( out, suf );
  678. X                        out = filelist + len;
  679. X                    }
  680. X                }
  681. X            }
  682. X            len += strlen( word );
  683. X            if( len + 1 < Param.MaxLine ) {
  684. X                if( out != filelist & how_fix ) {
  685. X                    *out++ = ' ';
  686. X                    len++;
  687. X                }
  688. X                strcpy( out, word );
  689. X                out = filelist + len;
  690. X            }
  691. X        } /* while */
  692. X        *out = (char)0;
  693. X        if( len > 0 ) mac->expansion = strdup( filelist );
  694. X    }
  695. X    free( filelist );
  696. X    return( 0 );
  697. X}
  698. X
  699. Xstatic int
  700. Xfn_addprefix( struct macro *mac, char *string )
  701. X{
  702. X    return( do_addfix( mac, string, 0 ));
  703. X}
  704. X
  705. Xstatic int
  706. Xfn_addsuffix( struct macro *mac, char *string )
  707. X{
  708. X    return( do_addfix( mac, string, 1 ));
  709. X}
  710. X
  711. Xstatic int
  712. Xdo_filter( struct macro *mac, char *string, int how_filter )
  713. X{
  714. X    char *str = string;
  715. X    char *pat;
  716. X    int len;
  717. X
  718. X    while( isspace( *str )) str++;
  719. X    pat = str;
  720. X    while( *str && *str != ',' && str[-1] != '\\' ) str++;
  721. X    if( *pat != ',' && *str == ',' && str[-1] != '\\' ) {
  722. X        char word[ 80 ];
  723. X        char *text, *out;
  724. X
  725. X        *str++ = (char)0;
  726. X
  727. X        if( !( mac->expansion = strdup( str )))
  728. X            return( 0 ); /* no mem */
  729. X        out = mac->expansion;
  730. X
  731. X        for( text = out;; ) {
  732. X            text = parse_str( word, text, sizeof(word));
  733. X            if( !*word ) break; /* no more words in text */
  734. X
  735. X            if( how_filter ) {
  736. X                if( ismatch( pat, word )) {
  737. X                    out = text + 1;
  738. X                }
  739. X                else { /* no match remove it */
  740. X                    while( isspace( *text )) text++;
  741. X                    shift_string_left( out, (int)(text - out));
  742. X                    text = out;
  743. X                }
  744. X            }
  745. X            else {
  746. X                if( ismatch( pat, word )) {
  747. X                    while( isspace( *text )) text++;
  748. X                    shift_string_left( out, (int)(text - out));
  749. X                    text = out;
  750. X                }
  751. X                else { /* no match remove it */
  752. X                    out = text + 1;
  753. X                }
  754. X            }
  755. X        } /* for */
  756. X        *out = (char)0;
  757. X        return( 0 );
  758. X    }
  759. X    logprintf( argument_missing, "filter", string );
  760. X    return( 1 );
  761. X}
  762. X
  763. Xstatic int
  764. Xfn_filter( struct macro *mac, char *string )
  765. X{
  766. X    return( do_filter( mac, string, 1 ));
  767. X}
  768. X
  769. Xstatic int
  770. Xfn_filter_out( struct macro *mac, char *string )
  771. X{
  772. X    return( do_filter( mac, string, 0 ));
  773. X}
  774. X
  775. Xstatic int
  776. Xfn_findstring( struct macro *mac, char *string )
  777. X{
  778. X    char *find, *in, *str = string;
  779. X    int len;
  780. X    
  781. X    while( isspace( *str )) str++;
  782. X    find = str;
  783. X    while( *str && *str != ',' && str[-1] != '\\' ) str++;
  784. X    if( *find != ',' && *str == ',' && str[-1] != '\\' ) {
  785. X        *str++ = (char)0;
  786. X        in = str;
  787. X        while( *str ) str++;    /* find end string */
  788. X        len = strlen( find );
  789. X        str -= len;    /* str marks the end of searching */
  790. X
  791. X        while( in <= str ) {
  792. X            /* logprintf( "looking for \"%s\" in \"%s\"\n", find, in ); */
  793. X
  794. X            if( !strncmp( find, in, len )) { /* found */
  795. X                mac->expansion = strdup( find );
  796. X                break;
  797. X            }
  798. X            in++; 
  799. X        }
  800. X    }
  801. X    else {
  802. X        logprintf( argument_missing, "findstring", string );
  803. X        return( 1 );
  804. X    }
  805. X    return( 0 );
  806. X}
  807. X
  808. Xstatic int
  809. Xfn_strip( struct macro *mac, char *str )
  810. X{
  811. X    while( isspace( *str )) str++;
  812. X    if( *str && (mac->expansion = strdup( str ))) {
  813. X        register char *d = mac->expansion;
  814. X        register char *s = mac->expansion;
  815. X        while( *s ) {
  816. X            *d++ = *s;
  817. X            if( isspace(*s)) while( isspace( *s)) s++;
  818. X            else s++;
  819. X        }
  820. X        if( isspace( *d )) {
  821. X            while( isspace( *d ) && d > mac->expansion ) d--;
  822. X            d++;
  823. X        }
  824. X        *d = (char)0;
  825. X    }
  826. X    return( 0 );
  827. X}
  828. X
  829. Xstatic int
  830. Xfn_subst( struct macro *mac, char *string )
  831. X{
  832. X    char *str = string;
  833. X    char *from, *to, *text;
  834. X    int len;
  835. X    
  836. X    while( isspace( *str )) str++;
  837. X    from = str;
  838. X    while( *str && *str != ',' && str[-1] != '\\' ) str++;
  839. X    if( *from != ',' && *str == ',' && str[-1] != '\\' ) {
  840. X        *str++ = (char)0;
  841. X        to = str;
  842. X        while( *str && *str != ',' && str[-1] != '\\' ) str++;
  843. X        if( *to != ',' && *str == ',' && str[-1] != '\\' && str[ 1 ] ) {
  844. X            *str++ = (char)0;
  845. X            text = str;
  846. X            while( *str ) str++;    /* find end string */
  847. X            len = strlen( from );
  848. X
  849. X            if( strlen( to ) != len ) {
  850. X                logprintf( "subst: args not the same size %s,%s\n",
  851. X                    from, to );
  852. X                return( 1 );
  853. X            }
  854. X
  855. X            text = mac->expansion = strdup( text );
  856. X            str = text + strlen( text ) - len; /* end of search */
  857. X            while( text <= str ) {
  858. X                if( !strncmp( from, text, len )) { /* found */
  859. X                    strncpy( text, to, len );
  860. X                }
  861. X                text++; 
  862. X            }
  863. X            return( 0 );
  864. X        }
  865. X    }
  866. X    logprintf( argument_missing, "subst", string );
  867. X    return( 1 );
  868. X}
  869. X
  870. Xstatic int
  871. Xfn_wildcard( struct macro *mac, char *string )
  872. X{
  873. X    char *filelist = NULL;
  874. X    char *pat = string;
  875. X
  876. X    filelist = (char *)calloc( Param.MaxLine, 1 );
  877. X    if( !filelist ) {
  878. X        logfile( error_no_memory );
  879. X        return( 1 );
  880. X    }
  881. X    while( isspace( *pat )) pat++;
  882. X    if( *pat ) {
  883. X        char *out = filelist;
  884. X        char *fn;
  885. X        int len = 0;
  886. X
  887. X        while( len < Param.MaxLine ) {
  888. X            if( !(fn = scdir( pat ))) break; /* no more */
  889. X            if( out != filelist ) {
  890. X                *out++ = ' ';
  891. X                len++;
  892. X            }
  893. X            len += strlen( fn );
  894. X            if( len < Param.MaxLine ) {
  895. X                strcpy( out, fn );
  896. X                out = filelist + len;
  897. X            }
  898. X        }
  899. X        if( len > 0 ) mac->expansion = strdup( filelist );
  900. X        scdir_abort();
  901. X    }
  902. X    free( filelist );
  903. X    return( 0 );
  904. X}
  905. X
  906. X
  907. Xint
  908. Xdo_word( struct macro *mac, char *string, int word )
  909. X{
  910. X    char *begin, *end;
  911. X
  912. X    if( begin = find_word( string, word )) {
  913. X        end = begin;
  914. X        while( *end && !isspace( *end )) end++;
  915. X        *end = (char)0; /* null terminate past the end of word */
  916. X        mac->expansion = strdup( begin );
  917. X    }
  918. X    return( 0 );
  919. X}
  920. X
  921. Xstatic int
  922. Xfn_firstword( struct macro *mac, char *string )
  923. X{
  924. X    while( isspace( *string )) string++;
  925. X    return( do_word( mac, string, 1 ));
  926. X}
  927. X
  928. Xstatic int
  929. Xfn_word( struct macro *mac, char *string )
  930. X{
  931. X    char *comma;
  932. X    int word;
  933. X
  934. X    while( isspace( *string )) string++;
  935. X    if( *string && (comma = find_token( string, ',' ))) {
  936. X        *comma = (char)0;
  937. X        word = atoi( string );
  938. X        /* else word not found */
  939. X        return( do_word( mac, comma + 1, word ));
  940. X    }
  941. X    logprintf( argument_missing, "word", string );
  942. X    return( 1 );
  943. X}
  944. X
  945. Xstatic int
  946. Xfn_words( struct macro *mac, char *string )
  947. X{
  948. X    char buf[ 20 ];
  949. X    sprintf( buf, "%d", count_args( string ));
  950. X    mac->expansion = strdup( buf );
  951. X    return( 0 );
  952. X}
  953. X
  954. Xstatic int
  955. Xfn_notimp( struct macro *mac, char *string )
  956. X{
  957. X    logfile( "Function call not implemented\n" );
  958. X    return( 1 );
  959. X}
  960. X
  961. X/*************************************************************************/
  962. X
  963. X/* sorted array for binary search */
  964. X#define MAX_FNCALL 21
  965. Xstatic struct fncall fncarray[ MAX_FNCALL ] = {
  966. X    "addprefix",    fn_addprefix,
  967. X    "addsuffix",    fn_addsuffix,
  968. X    "basename",        fn_basename,
  969. X    "dir",            fn_notimp,
  970. X    "filter",        fn_filter,
  971. X    "filter-out",    fn_filter_out,
  972. X    "findstring",    fn_findstring,
  973. X    "firstword",    fn_firstword,
  974. X    "foreach",        fn_notimp,
  975. X    "join",            fn_notimp,
  976. X    "notdir",        fn_notimp,
  977. X    "origin",        fn_notimp,
  978. X    "patsubst",        fn_notimp,
  979. X    "shell",        fn_notimp,
  980. X    "sort",            fn_notimp,
  981. X    "strip",        fn_strip,
  982. X    "subst",        fn_subst,
  983. X    "suffix",        fn_notimp,
  984. X    "wildcard",        fn_wildcard,
  985. X    "word",            fn_word,
  986. X    "words",        fn_words
  987. X};
  988. X
  989. X/*    binary search to find the function */
  990. Xstruct fncall *
  991. Xfind_fncall( char *name )
  992. X{
  993. X    register struct fncall *array = fncarray;
  994. X    int first = 0L;
  995. X    int last = MAX_FNCALL - 1;
  996. X    int mid;
  997. X    int diff;
  998. X
  999. X    /* binary search */
  1000. X    while( first <= last ) {
  1001. X        mid = (first+last) / 2;
  1002. X        diff = strcmp( name, array[ mid ].name );
  1003. X        if( !diff )
  1004. X            return( &array[ mid ] ); /* found */
  1005. X        if( first == last ) break; /* not found */
  1006. X        if( diff < 0 ) last = mid - 1;
  1007. X        else first = mid + 1;
  1008. X    }
  1009. X    return( NULL ); /* not found */
  1010. X}
  1011. X
  1012. X#else
  1013. X
  1014. X/*    No FNCALLS */
  1015. Xstruct fncall *
  1016. Xfind_fncall( char *name )
  1017. X{
  1018. X    return( NULL ); /* not found */
  1019. X}
  1020. X
  1021. X#endif
  1022. X
  1023. END_OF_FILE
  1024. if test 10300 -ne `wc -c <'fncall.c'`; then
  1025.     echo shar: \"'fncall.c'\" unpacked with wrong size!
  1026. fi
  1027. # end of 'fncall.c'
  1028. fi
  1029. if test -f 'input.c' -a "${1}" != "-c" ; then 
  1030.   echo shar: Will not clobber existing file \"'input.c'\"
  1031. else
  1032. echo shar: Extracting \"'input.c'\" \(7586 characters\)
  1033. sed "s/^X//" >'input.c' <<'END_OF_FILE'
  1034. X/*    input.c
  1035. X *  (c) Copyright 1991 by Ben Eng, All Rights Reserved
  1036. X *
  1037. X */
  1038. X
  1039. X#include <ctype.h>
  1040. X#include <clib/exec_protos.h>
  1041. X
  1042. X#include "make.h"
  1043. X#include "depend.h"
  1044. X
  1045. Xint line_number;
  1046. X
  1047. Xstatic struct List Mstack =
  1048. X{
  1049. X    (struct Node *)&Mstack.lh_Tail,    /* lh_Head */
  1050. X    (struct Node *)NULL,            /* lh_Tail */
  1051. X    (struct Node *)&Mstack.lh_Head,    /* lh_TailPred */
  1052. X    (UBYTE)NT_USER,
  1053. X    (UBYTE)0
  1054. X};
  1055. X
  1056. X#define STATE_IF_T    1
  1057. X#define STATE_IF_F    2    /* skip lines mode */
  1058. X#define STATE_EL_T    3    /* skip lines mode */
  1059. X#define STATE_EL_F    4
  1060. X
  1061. Xstatic struct mstate {
  1062. X    struct Node node;
  1063. X    int state;
  1064. X};
  1065. X
  1066. Xstatic struct drctvs {
  1067. X    char *directive;    /* the name of the directive */
  1068. X    int (*call)(char *);    /* function call */
  1069. X};
  1070. X
  1071. X/*    binary search to find the function */
  1072. Xstruct drctvs *
  1073. Xfind_drctvs( struct drctvs *array, int array_size, char *name )
  1074. X{
  1075. X    int first = 0L;
  1076. X    int last = array_size - 1;
  1077. X    int mid;
  1078. X    int diff, len;
  1079. X
  1080. X    /* binary search */
  1081. X    while( first <= last ) {
  1082. X        mid = (first+last) / 2;
  1083. X        len = strlen( array[ mid ].directive );
  1084. X        diff = strncmp( name, array[ mid ].directive, len );
  1085. X        if( !diff ) return( &array[ mid ] ); /* found */
  1086. X        if( first == last ) break; /* not found */
  1087. X        if( diff < 0 ) last = mid - 1;
  1088. X        else first = mid + 1;
  1089. X    }
  1090. X    return( NULL ); /* not found */
  1091. X}
  1092. X
  1093. Xstatic int
  1094. Xpush_state( struct List *stack, long state )
  1095. X{
  1096. X    struct mstate *new = (struct mstate *)malloc( sizeof(struct mstate));
  1097. X    if( !new ) return( 1 ); /* no memory */
  1098. X    new->node.ln_Type = NT_USER;
  1099. X    new->state = state;
  1100. X    AddHead( stack, &new->node );
  1101. X    return( 0 );
  1102. X}
  1103. X
  1104. Xstatic int
  1105. Xpop_state( struct List *stack )
  1106. X{
  1107. X    struct mstate *new = (struct mstate *)RemHead( stack );
  1108. X    int state;
  1109. X    if( !new ) return( 0 ); /* no state */
  1110. X    state = new->state;
  1111. X    free( new );
  1112. X    return( state );
  1113. X}
  1114. X
  1115. Xstatic void
  1116. Xclear_stack( struct List *stack )
  1117. X{
  1118. X    struct Node *node, *succ;
  1119. X
  1120. X    for( node = stack->lh_Head; node->ln_Succ; node = succ ) {
  1121. X        succ = node->ln_Succ;
  1122. X        free( node );
  1123. X    }
  1124. X    NewList( stack );
  1125. X}
  1126. X
  1127. X/*    returns true if we are still within a conditional */
  1128. Xint
  1129. Xget_directive_state( void )
  1130. X{
  1131. X    struct mstate *first = (struct mstate *)Mstack.lh_Head;
  1132. X    if( !first->node.ln_Succ ) return( 0 );
  1133. X    return( first->state );
  1134. X}
  1135. X
  1136. X/* conditions return 0 for false, 1 for true, -1 for error */
  1137. Xstatic int
  1138. Xdo_condeq( char *string, int negate )
  1139. X{
  1140. X    char *exp1 = NULL, *exp2 = NULL;
  1141. X    char *lparen = string, *comma, *rparen;
  1142. X    int retval = -1; /* default to error */
  1143. X
  1144. X    exp1 = (char*)malloc( Param.MaxLine );
  1145. X    exp2 = (char*)malloc( Param.MaxLine );
  1146. X    if( !exp1 || !exp2 ) goto death;
  1147. X
  1148. X    while( *lparen && *lparen != '(' ) lparen++;
  1149. X    if( *lparen != '(' ) goto death;
  1150. X    comma = lparen + 1;
  1151. X    while( *comma && *comma != ',' ) comma++;
  1152. X    if( *comma != ',' ) goto death;
  1153. X    rparen = comma + 1;
  1154. X    while( *rparen && *rparen != ')' ) rparen++;
  1155. X    if( *rparen != ')' ) goto death;
  1156. X
  1157. X    *comma = *rparen = (char)0;
  1158. X    if( expand_macros( exp1, lparen + 1, Param.MaxLine ) ||
  1159. X        expand_macros( exp2, comma + 1, Param.MaxLine )) goto death;
  1160. X
  1161. X    if( negate )
  1162. X        retval = strcmp( exp1, exp2 ) ? 1 : 0; /* set condition code */
  1163. X    else
  1164. X        retval = strcmp( exp1, exp2 ) ? 0 : 1; /* set condition code */
  1165. X
  1166. Xdeath:
  1167. X    if( exp1 ) free( exp1 );
  1168. X    if( exp2 ) free( exp2 );
  1169. X    return( retval );
  1170. X}
  1171. X
  1172. Xstatic int
  1173. Xdo_conddef( char *string, int negate )
  1174. X{
  1175. X    char *lparen = string, *rparen;
  1176. X    char *exp1 = NULL;
  1177. X    int retval = -1; /* default to error */
  1178. X
  1179. X    exp1 = (char *)malloc( Param.MaxLine );
  1180. X    if( !exp1 ) goto death;
  1181. X
  1182. X    while( *lparen && *lparen != '(' ) lparen++;
  1183. X    if( *lparen != '(' ) goto death;
  1184. X    rparen = lparen + 1;
  1185. X    while( *rparen && *rparen != ')' ) rparen++;
  1186. X    if( *rparen != ')' ) goto death;
  1187. X
  1188. X    *rparen = (char)0;
  1189. X    retval = find_macro( lparen + 1 ) ? 1 : 0;
  1190. X    if( negate ) retval = retval ? 0 : 1;
  1191. Xdeath:
  1192. X    if( exp1 ) free( exp1 );
  1193. X    return( retval );
  1194. X}
  1195. X
  1196. Xstatic int
  1197. Xcdrctv_eq( char *string )
  1198. X{
  1199. X    return( do_condeq( string, 0 ));
  1200. X}
  1201. Xstatic int
  1202. Xcdrctv_neq( char *string )
  1203. X{
  1204. X    return( do_condeq( string, 1 ));
  1205. X}
  1206. X
  1207. Xstatic int
  1208. Xcdrctv_def( char *string )
  1209. X{
  1210. X    return( do_conddef( string, 0 ));
  1211. X}
  1212. Xstatic int
  1213. Xcdrctv_ndef( char *string )
  1214. X{
  1215. X    return( do_conddef( string, 1 ));
  1216. X}
  1217. X
  1218. X/* keep it sorted for binary search */
  1219. X#define MAX_CDRCTVS 4
  1220. Xstatic struct drctvs carray[ MAX_CDRCTVS ] = {
  1221. X    { "def",     cdrctv_def    },
  1222. X    { "eq",      cdrctv_eq    },
  1223. X    { "ndef",    cdrctv_ndef    },
  1224. X    { "neq",     cdrctv_neq    }
  1225. X};
  1226. X
  1227. Xstatic int
  1228. Xdrctv_else( char *string )
  1229. X{
  1230. X    int state = pop_state( &Mstack );
  1231. X    int newstate = 0;
  1232. X
  1233. X    if( state != STATE_IF_T && state != STATE_IF_F ) {
  1234. X        logfile( "ERROR:  else with no matching conditional\n" );
  1235. X        return( 1 );
  1236. X    }
  1237. X    newstate = (state == STATE_IF_T) ? STATE_EL_T : STATE_EL_F;
  1238. X    debugprintf( 4, ("else changes state from %d to %d\n",
  1239. X        state, newstate ));
  1240. X    push_state( &Mstack, newstate );
  1241. X    return( 0 );
  1242. X}
  1243. X
  1244. Xstatic int
  1245. Xdrctv_endif( char *string )
  1246. X{
  1247. X    int state = pop_state( &Mstack );
  1248. X
  1249. X    if( !state ) {
  1250. X        logfile( "ERROR:  endif with no matching conditional\n" );
  1251. X        return( 1 );
  1252. X    }
  1253. X    return( 0 );
  1254. X}
  1255. X
  1256. Xstatic int
  1257. Xdrctv_if( char *string )
  1258. X{
  1259. X    struct drctvs *cdrctv;
  1260. X    int condition;
  1261. X
  1262. X    while( isspace( *string )) string++;
  1263. X    if( !*string ) {
  1264. X        logfile( "No condition given\n" );
  1265. X        return( 1 );
  1266. X    }
  1267. X
  1268. X    if( cdrctv = find_drctvs( carray, MAX_CDRCTVS, string )) {
  1269. X        debugprintf( 4, ("condition %s\n", string ));
  1270. X        condition = (*cdrctv->call)( string + strlen( cdrctv->directive ));
  1271. X        debugprintf( 4, ("condition returns %d\n", condition ));
  1272. X        if( condition < 0 ) {
  1273. X            logprintf( "Error in condition: %s\n", string );
  1274. X            return( 1 );
  1275. X        }
  1276. X        else if( condition ) { /* execute the true code */
  1277. X            push_state( &Mstack, STATE_IF_T );
  1278. X            return( 0 );
  1279. X        }
  1280. X        else {    /* execute the false code */
  1281. X            push_state( &Mstack, STATE_IF_F );
  1282. X            return( 0 );
  1283. X        }
  1284. X    }
  1285. X    logprintf( "Unrecognized condition: %s\n", string );
  1286. X    return( 1 );
  1287. X}
  1288. X
  1289. Xstatic int
  1290. Xdrctv_pragma( char *string )
  1291. X{
  1292. X    int i, arguments, retval = 1;
  1293. X    char **argv = NULL;
  1294. X
  1295. X    while( isspace( *string )) string++;
  1296. X    if( arguments = count_args( string ) + 1) {
  1297. X        if( argv = (char **)malloc( (arguments + 1) * sizeof(char *)) ) {
  1298. X            for( i = 1; i < arguments; i++ ) {
  1299. X                argv[ i ] = find_word( string, i );
  1300. X            }
  1301. X            argv[ 0 ] = version_string + 7;
  1302. X            argv[ arguments ] = NULL;
  1303. X            retval = parse_parameters( arguments, argv );
  1304. X            free( argv );
  1305. X        }
  1306. X    }
  1307. X    debugprintf( 3,( "Pragma(%d,%s)\n", arguments, string ));
  1308. X    return( retval );
  1309. X}
  1310. X
  1311. X/* keep it sorted for binary search */
  1312. X#define MAX_MDRCTVS 4
  1313. Xstatic struct drctvs darray[ MAX_MDRCTVS ] = {
  1314. X    { "else",    drctv_else    },
  1315. X    { "endif",    drctv_endif    },
  1316. X    { "if",        drctv_if    },
  1317. X    { "pragma",    drctv_pragma }
  1318. X};
  1319. X
  1320. X/*    get a non-comment line
  1321. X */
  1322. Xstatic int
  1323. Xget_ncline( char *buf, int sz, FILE *in )
  1324. X{
  1325. X    char *inbuf, *cptr;
  1326. X    int total, len;
  1327. X
  1328. X    do {
  1329. X        if( feof( in )) return( 1 );
  1330. X        if( !fgets( buf, sz, in )) return( 1);
  1331. X        line_number++;
  1332. X        total = strlen( buf );
  1333. X        inbuf = buf;
  1334. X        while( cptr = strrchr( inbuf, '\\' ) ){
  1335. X            if( cptr[1] != '\n' ) break;
  1336. X            total -= 2; /* subtract backslash newline */
  1337. X            inbuf = cptr;
  1338. X            if( total >= sz ) break;
  1339. X            if( feof( in )) return( 1 );
  1340. X            if( !fgets( inbuf, sz - total, in )) return( 1 );
  1341. X            line_number++;
  1342. X            total += strlen( inbuf );
  1343. X        }
  1344. X    } while( *buf == '#' );
  1345. X    strip_trailspace( buf );
  1346. X    return( 0 );
  1347. X}
  1348. X
  1349. X/*    get the next valid line from a Makefile
  1350. X */
  1351. Xint
  1352. Xgetline( char *buf, int sz, FILE *in )
  1353. X{
  1354. X    struct drctvs *found = NULL;
  1355. X    int st, state = 0;
  1356. X    do {
  1357. X        if( state && !found )
  1358. X            debugprintf( 4, ("skipped[state=%d] %s\n", state, buf ));
  1359. X        st = get_ncline( buf, sz, in );
  1360. X        if( !st ) {
  1361. X            if( found = find_drctvs( darray, MAX_MDRCTVS, buf )) {
  1362. X                if( st = (*found->call)( buf + strlen( found->directive )))
  1363. X                    clear_stack( &Mstack );
  1364. X            }
  1365. X        }
  1366. X        state = get_directive_state();
  1367. X    } while( !st && (state == STATE_IF_F || state == STATE_EL_T || found ));
  1368. X
  1369. X    return( st );
  1370. X}
  1371. X
  1372. END_OF_FILE
  1373. if test 7586 -ne `wc -c <'input.c'`; then
  1374.     echo shar: \"'input.c'\" unpacked with wrong size!
  1375. fi
  1376. # end of 'input.c'
  1377. fi
  1378. if test -f 'make.c' -a "${1}" != "-c" ; then 
  1379.   echo shar: Will not clobber existing file \"'make.c'\"
  1380. else
  1381. echo shar: Extracting \"'make.c'\" \(5200 characters\)
  1382. sed "s/^X//" >'make.c' <<'END_OF_FILE'
  1383. X/*    make.c
  1384. X *  (c) Copyright 1991 by Ben Eng, All Rights Reserved
  1385. X *
  1386. X */
  1387. X
  1388. X#include <string.h>
  1389. X#include <ctype.h>
  1390. X#include <fcntl.h>
  1391. X
  1392. X#include <clib/exec_protos.h>
  1393. X#include <clib/dos_protos.h>
  1394. X
  1395. X#include "make.h"
  1396. X#include "depend.h"
  1397. X
  1398. Xstatic int make_implicit( char *goalname, int *remake_flag );
  1399. X
  1400. X/*
  1401. X *        Get the modification time of a file.  If the first
  1402. X *        doesn't exist, it's modtime is set to 0.
  1403. X */
  1404. X
  1405. Xtime_t
  1406. Xmodtime( char *filename )
  1407. X{
  1408. X    struct FileInfoBlock *fib;
  1409. X    BPTR myLock;
  1410. X    long ioErr;
  1411. X    time_t mtime = 0L;
  1412. X
  1413. X    fib = (struct FileInfoBlock *)malloc( sizeof(struct FileInfoBlock));
  1414. X    if( fib ) {
  1415. X        if( !(myLock = Lock( filename, ACCESS_READ ))) {
  1416. X            if( (ioErr = IoErr()) != ERROR_OBJECT_NOT_FOUND)
  1417. X                logprintf( "Can't Lock '%s'; error %ld\n", filename, ioErr );
  1418. X        }
  1419. X        else if( !Examine( myLock, fib )) {
  1420. X            UnLock(myLock);
  1421. X            logprintf( "Can't Examine '%s'; error %ld", filename, IoErr() );
  1422. X        }
  1423. X        else {
  1424. X            mtime = fib->fib_Date.ds_Tick / TICKS_PER_SECOND +
  1425. X                 60*fib->fib_Date.ds_Minute + 86400 * fib->fib_Date.ds_Days;
  1426. X            UnLock( myLock );
  1427. X        }
  1428. X        free( fib );
  1429. X    }
  1430. X    return( mtime );
  1431. X}
  1432. X
  1433. X/* return true if targ1 is newer than targ2 */
  1434. Xint
  1435. Xisnewer( char *targ1, char *targ2 )
  1436. X{
  1437. X    time_t t1, t2;
  1438. X    long diff;
  1439. X    int retval;
  1440. X
  1441. X    t1 = modtime( targ1 );
  1442. X    t2 = modtime( targ2 );
  1443. X    diff = (long)(t1 - t2);
  1444. X    retval = (diff > 0L) ? 1 : 0;
  1445. X
  1446. X    debugprintf( 5, ("isnewer %s=%ld,%s=%ld diff=%ld: %s\n", targ1, t1,
  1447. X        targ2, t2, diff, (retval) ? "yes" : "no" ));
  1448. X
  1449. X    return( retval );
  1450. X}
  1451. X
  1452. X/* recursively make a target filename */
  1453. Xint
  1454. Xmake_filename( const char *goalname, int *made )
  1455. X{
  1456. X    int remake_flag = (Param.all_mode) ? 1 : 0;    
  1457. X    struct depend *dep;
  1458. X    struct List *cmdlist;
  1459. X    struct target *goal = find_target( goalname );
  1460. X    char *depname = NULL;
  1461. X
  1462. X    Global.recursion_level++;
  1463. X    *made = 0;
  1464. X
  1465. X    if( Global.recursion_level == 1 ) {
  1466. X        logprintf( "\tmake( %s )\n", goalname );
  1467. X    }
  1468. X    else  {
  1469. X        debugprintf( 1, ( "\n\tmake %d ( %s )\n", Global.recursion_level,
  1470. X        goalname ));
  1471. X    }
  1472. X    if( goal ) {
  1473. X        if( goal->dependlist.lh_Head->ln_Succ ) {
  1474. X            for( dep = (struct depend *)goal->dependlist.lh_Head; 
  1475. X                dep->node.ln_Succ; dep = dep->node.ln_Succ ) {
  1476. X                int made_flag;
  1477. X
  1478. X                debugprintf( 1, ("%s depends on %s\n", goalname, dep->name ));
  1479. X                if( make_filename( dep->name, &made_flag )) return( 1 );
  1480. X                if( made_flag || isnewer( dep->name, goalname )) {
  1481. X                    depname = dep->name;
  1482. X                    remake_flag = 1;
  1483. X                }
  1484. X            } /* for */
  1485. X        } /* if has dependencies */
  1486. X        else remake_flag = 1;
  1487. X    } /* if */
  1488. X
  1489. X    /* if no explicit rule for goal OR goal has no commands */
  1490. X    if( !goal || !goal->commandlist.lh_Head->ln_Succ ) {
  1491. X        int retval = make_implicit( goalname, &remake_flag );
  1492. X        --Global.recursion_level;
  1493. X        *made = remake_flag;
  1494. X        return( retval ); /* illegal reuse of remake_flag :-) */
  1495. X    }
  1496. X
  1497. X    --Global.recursion_level;
  1498. X
  1499. X    if( remake_flag ) {
  1500. X        struct List *cmdlist;
  1501. X        int retval;
  1502. X
  1503. X        cmdlist = (goal->flags & TF_OWNER ) ? &goal->commandlist :
  1504. X            goal->alternate;
  1505. X        if( cmdlist->lh_Head->ln_Succ ) {
  1506. X            set_target_macros( goalname, depname );
  1507. X            retval = recipe( goalname, cmdlist );
  1508. X            set_target_macros( NULL, NULL );
  1509. X            if( retval ) return( 1 );
  1510. X            *made = 1;
  1511. X        }
  1512. X    }
  1513. X    else {
  1514. X        debugprintf( 2,("%s is up to date\n", goal->name ));
  1515. X    }
  1516. X    return( 0 );
  1517. X}
  1518. X
  1519. X/*    use this inference engine as a last resort
  1520. X *    use suffix rules to determine dependencies and commands for goalname
  1521. X */
  1522. Xstatic int
  1523. Xmake_implicit( char *goalname, int *remake_flag )
  1524. X{
  1525. X    char *depfile = (char *)malloc( MAXPATHNAME );
  1526. X    char *depname = NULL;
  1527. X    struct suffixrule *sr;
  1528. X    char *dot;
  1529. X    char suf[ MAXSUFFIX ];
  1530. X
  1531. X    debugprintf( 1, ("\tmake_implicit( %s )\n", goalname ));
  1532. X                
  1533. X    if( !depfile ) goto death; /* no mem */
  1534. X
  1535. X    dot = strrchr( goalname, '.' );
  1536. X    if( !dot ) goto out;
  1537. X
  1538. X    strcpy( suf, dot + 1 );
  1539. X    for( sr = &Global.suffixlist.lh_Head; sr->node.ln_Succ;
  1540. X        sr = sr->node.ln_Succ ) {
  1541. X        if( !strcmp( suf, sr->tar_suf ) ) {
  1542. X            debugprintf( 2, ("Matched Suffix rule .%s.%s to %s\n",
  1543. X                sr->dep_suf, sr->tar_suf, goalname ));
  1544. X            if( *sr->dep_suf ) {
  1545. X                strcpy( depfile, goalname );
  1546. X                dot = strrchr( depfile, '.' );
  1547. X                strcpy( dot + 1, sr->dep_suf );
  1548. X                if( !access( depfile, 0 )) { /* found it */
  1549. X                    int made_flag;
  1550. X                    depname = depfile;
  1551. X                    debugprintf( 2, ("double suffix rule matches %s\n",
  1552. X                        depname ));
  1553. X                    if( make_filename( depname, &made_flag )) {
  1554. X                        goto death;
  1555. X                    }
  1556. X                    if( made_flag || isnewer( depname, goalname ))
  1557. X                        *remake_flag = 1;
  1558. X                    break;
  1559. X                } /* else not the right rule, continue to find another */
  1560. X            }
  1561. X            else {
  1562. X                debugprintf( 2, ("single suffix rule applies\n" ));
  1563. X                *remake_flag = 1;
  1564. X                break;
  1565. X            }
  1566. X        } /* if */
  1567. X    } /* for each suffix rule */
  1568. X
  1569. X    if( !sr->node.ln_Succ ) {
  1570. X        logprintf( "don't know how to make %s\n", goalname );
  1571. X        goto death;
  1572. X    }
  1573. X    if( *remake_flag ) {
  1574. X        struct List *cmdlist;
  1575. X        struct target *goal = sr->targ;
  1576. X
  1577. X        set_target_macros( goalname, depname );
  1578. X
  1579. X        cmdlist = (goal->flags & TF_OWNER ) ? &goal->commandlist :
  1580. X            goal->alternate;
  1581. X        if( cmdlist->lh_Head->ln_Succ ) {
  1582. X            if( recipe( goalname, cmdlist )) goto death;
  1583. X        }
  1584. X        else *remake_flag = 0;
  1585. X        set_target_macros( NULL, NULL );
  1586. X    }
  1587. X    else {
  1588. X        debugprintf( 2,("%s is up to date\n", goalname ));
  1589. X    }
  1590. Xout:
  1591. X    free( depfile );
  1592. X    return( 0 );
  1593. Xdeath:
  1594. X    if( depfile ) free( depfile );
  1595. X    return( 1 );
  1596. X}
  1597. END_OF_FILE
  1598. if test 5200 -ne `wc -c <'make.c'`; then
  1599.     echo shar: \"'make.c'\" unpacked with wrong size!
  1600. fi
  1601. # end of 'make.c'
  1602. fi
  1603. if test -f 'read.c' -a "${1}" != "-c" ; then 
  1604.   echo shar: Will not clobber existing file \"'read.c'\"
  1605. else
  1606. echo shar: Extracting \"'read.c'\" \(8514 characters\)
  1607. sed "s/^X//" >'read.c' <<'END_OF_FILE'
  1608. X/*    input.c
  1609. X *  (c) Copyright 1991 by Ben Eng, All Rights Reserved
  1610. X *
  1611. X */
  1612. X
  1613. X#include <ctype.h>
  1614. X#include <clib/exec_protos.h>
  1615. X
  1616. X#include "make.h"
  1617. X#include "depend.h"
  1618. X
  1619. Xextern int line_number;
  1620. X
  1621. X/*    process a line that looks like
  1622. X *    target names: dependencies
  1623. X */
  1624. Xstruct target *
  1625. Xprocess_targetline( char *line, struct List *cmdlist, int builtin_flag )
  1626. X{
  1627. X    struct target *first_targ = NULL;
  1628. X    struct target *targ = NULL;
  1629. X    struct List *ownerlist = NULL;
  1630. X    char *delim, *nexttar;
  1631. X    char name[ 80 ];
  1632. X    char *expandlhs = NULL, *expandrhs = NULL;
  1633. X    long len;
  1634. X
  1635. X    if( !(expandlhs = (char *)malloc( Param.MaxLine )) ||
  1636. X        !(expandrhs = (char *)malloc( Param.MaxLine ))) goto death;
  1637. X
  1638. X    while( isspace( *line )) line++;
  1639. X    delim = find_token( line + 1, ':' );
  1640. X    if( !delim ) goto death;
  1641. X    len = (long)(delim - line);
  1642. X    if( !len ) goto death;
  1643. X
  1644. X    memset( name, 0, sizeof( name ));
  1645. X    strncpy( name, line, delim - line );
  1646. X
  1647. X    /* expand macros in targetnames */
  1648. X    if( expand_macros( expandlhs, name, Param.MaxLine )) goto death;
  1649. X    nexttar = expandlhs;
  1650. X
  1651. X    if( !strcmp( ".SUFFIXES", expandlhs )) {
  1652. X        char suf[ MAXSUFFIX ];
  1653. X
  1654. X        nexttar = delim + 1;
  1655. X        while( isspace( *nexttar )) nexttar++;
  1656. X
  1657. X        /* expand macros in rhs */
  1658. X        if( *nexttar && expand_macros( expandrhs, nexttar, Param.MaxLine ))
  1659. X            goto death;
  1660. X        nexttar = expandrhs;
  1661. X
  1662. X        for( ; ; ) {
  1663. X            while( isspace( *nexttar )) nexttar++;
  1664. X            if( *nexttar != '.' ) {
  1665. X                if( *nexttar ) {
  1666. X                    printf( "bad suffix rule [%s] on line %d\n%s\n",
  1667. X                        nexttar, line_number, line );
  1668. X                }
  1669. X                break;
  1670. X            }
  1671. X            nexttar = parse_strtok( suf, ++nexttar, sizeof(suf)-1, isnotsuf );
  1672. X            if( !*suf ) break;
  1673. X            first_targ = add_suffix_targets( suf );
  1674. X        }
  1675. X        targ = NULL;
  1676. X        goto death;
  1677. X    }
  1678. X
  1679. X    /* for each target name left of the colon */
  1680. X    for(;;) {
  1681. X        struct depend *dep = NULL;
  1682. X        struct command *cmd = NULL;
  1683. X        char *next;
  1684. X        
  1685. X        nexttar = parse_str( name, nexttar, sizeof( name ));
  1686. X        if( !*name ) break; /* no more names */
  1687. X
  1688. X        targ = find_target( name );
  1689. X        if( !targ ) {
  1690. X            targ = new_target( name );
  1691. X            if( !targ )    goto death;
  1692. X            targ->line_number = line_number;
  1693. X        }
  1694. X        if( builtin_flag ) targ->flags |= TF_BUILTIN;
  1695. X
  1696. X        debugprintf( 5, ( "new target: %s\n", targ->name ) );
  1697. X
  1698. X        if( !first_targ ) {
  1699. X            first_targ = targ;
  1700. X            first_targ->flags |= TF_OWNER;
  1701. X            ownerlist = &targ->commandlist;
  1702. X        }
  1703. X
  1704. X        set_target_macros( name, NULL );
  1705. X
  1706. X        /* find the dependencies */
  1707. X        next = delim + 1;
  1708. X        while( isspace( *next )) next++;
  1709. X
  1710. X        /* expand macros in dependencies */
  1711. X        if( expand_macros( expandrhs, next, Param.MaxLine )) goto death;
  1712. X        next = expandrhs;
  1713. X
  1714. X        /* for each dependency add to list */
  1715. X        for( ;; ) {
  1716. X            next = parse_str( name, next, sizeof( name ));
  1717. X            if( !*name ) break; /* no more names */
  1718. X            /* first check if that dependency already exists */
  1719. X            for( dep = targ->dependlist.lh_Head; dep->node.ln_Succ;
  1720. X                dep = dep->node.ln_Succ ) {
  1721. X                if( !strcmp( dep->name, name )) break;
  1722. X            }
  1723. X
  1724. X            if( !dep->node.ln_Succ ) { /* doesn't exist already */
  1725. X                if(  dep = new_depend( name ))
  1726. X                    AddTail( &targ->dependlist, &dep->node );
  1727. X                else goto death;
  1728. X            }
  1729. X            else {
  1730. X                logprintf( "duplicate dependency %s for target %s\n",
  1731. X                    name, targ->name );
  1732. X            }
  1733. X        }
  1734. X        /* for each command add to list */
  1735. X        if( targ->flags & TF_OWNER ) {
  1736. X            delete_commandlist( &targ->commandlist );
  1737. X            attach_list( &targ->commandlist, cmdlist );
  1738. X        }
  1739. X        else targ->alternate = ownerlist;
  1740. X
  1741. X        if( !(targ->flags & TF_ADDED )) {
  1742. X            targ->flags |= TF_ADDED;
  1743. X            AddTail( &Global.targetlist, &targ->node );
  1744. X        }
  1745. X        targ = NULL;
  1746. X    } /* for */
  1747. X    set_target_macros( NULL, NULL ); /* delete $@ $* and $< */
  1748. X
  1749. Xdeath:
  1750. X    if( targ ) free( targ );
  1751. X    if( expandrhs ) free( expandrhs );
  1752. X    if( expandlhs ) free( expandlhs );
  1753. X    return( first_targ );
  1754. X}
  1755. X
  1756. X/*    process a line that looks like
  1757. X *    variable = value
  1758. X */
  1759. Xstruct macro *
  1760. Xprocess_macroline( char *line )
  1761. X{
  1762. X    struct macro *mac = NULL;
  1763. X    char *delim, *next;
  1764. X    char macroname[ MAX_MACRONAME ], *rhs;
  1765. X    char *expansion = NULL; /* dynamic */
  1766. X    long namelen, explen;
  1767. X    int do_expansion = 0;
  1768. X    int do_addition = 0;
  1769. X
  1770. X    debugprintf( 5, ( "macroline %d: %s\n", line_number, line ) );
  1771. X
  1772. X    while( isspace( *line )) line++; /* skip whitespace */
  1773. X
  1774. X    delim = strchr( line, '=' ); /* cannot be escaped by backslash */
  1775. X    if( !delim ) goto death;
  1776. X    rhs = delim + 1;
  1777. X
  1778. X    namelen = min( (long)(delim - line), sizeof(macroname)-1);
  1779. X    if( !namelen ) goto death;
  1780. X
  1781. X    switch( *(delim-1)) {
  1782. X    case ':':
  1783. X        do_expansion = 1;
  1784. X        delim--;
  1785. X        namelen--;
  1786. X        break;
  1787. X    case '+':
  1788. X        do_addition = 1;
  1789. X        delim--;
  1790. X        namelen--;
  1791. X        break;
  1792. X    }
  1793. X
  1794. X    next = line;
  1795. X    while( isspace( *next )) next++;
  1796. X    memset( macroname, 0, sizeof( macroname ));
  1797. X    for( int i = 0; next < delim && i < 79; i++ ) {
  1798. X        if( isspace( *next )) break;
  1799. X        macroname[ i ] = *next++;
  1800. X    }
  1801. X
  1802. X    while( isspace( *rhs )) rhs++; /* skip whitespace */
  1803. X
  1804. X    if( do_expansion && *rhs ) {
  1805. X        expansion = (char *)malloc( Param.MaxLine );
  1806. X        if( !expansion ) goto death;
  1807. X        if( expand_macros( expansion, rhs, Param.MaxLine )) goto death;
  1808. X            /* expand rhs */
  1809. X        rhs = expansion;
  1810. X    }
  1811. X
  1812. X    if( mac = find_macro( macroname )) {
  1813. X        char *old = mac->expansion;
  1814. X
  1815. X        if( do_addition && old ) {
  1816. X            if( mac->expansion = malloc(strlen( old ) + strlen( rhs ) + 1)) {
  1817. X                strcpy( mac->expansion, old );
  1818. X                strcat( mac->expansion, " " );
  1819. X                strcat( mac->expansion, rhs );
  1820. X            }
  1821. X        }
  1822. X        else mac->expansion = strdup( rhs );
  1823. X        if( old ) free( old );
  1824. X    }
  1825. X    else mac = new_macro( macroname, rhs );
  1826. X
  1827. X    if( mac ) {
  1828. X        if( do_expansion ) mac->flags |= MF_SIMPLE;
  1829. X        if( !(mac->flags & MF_ADDED )) {
  1830. X            mac->flags |= MF_ADDED;
  1831. X            AddTail( &Global.macrolist, &mac->node );
  1832. X        }
  1833. X        debugprintf( 5, ( "assigned macro [%s] = [%s]\n",
  1834. X            mac->name, mac->expansion ));
  1835. X    }
  1836. X    else {
  1837. X        debugprintf( 2, ("error assigning macro [%s]\n", macroname ) );
  1838. X    }
  1839. X
  1840. X    if( expansion ) free( expansion );
  1841. X    return( mac );
  1842. Xdeath:
  1843. X    if( expansion ) free( expansion );
  1844. X    if( mac ) free( mac );
  1845. X    return( NULL );
  1846. X}
  1847. X
  1848. X/*    read in all rules and variables from this makefile
  1849. X*/
  1850. Xint
  1851. Xinput_makefile( const char *makefile, int builtin_flag )
  1852. X{
  1853. X    char *curline = NULL;
  1854. X    char *commandline = NULL;
  1855. X    FILE *infile = NULL;
  1856. X    int targetcount = 0, macrocount = 0;
  1857. X    int st;
  1858. X
  1859. X    curline = (char *)malloc( Param.MaxLine );
  1860. X    commandline = (char *)malloc( Param.MaxLine );
  1861. X    if( !curline || !commandline ) goto death;
  1862. X
  1863. X    infile = fopen( makefile, "r" );
  1864. X    if( !infile ) {
  1865. X        logprintf( "Cannot open %s\n", makefile );
  1866. X        goto death;
  1867. X    }
  1868. X
  1869. X    debugprintf( 3,( "input Makefile: %s\n", makefile ));
  1870. X
  1871. X    line_number = 0;
  1872. X    if( st = getline( curline, Param.MaxLine, infile )) goto death;
  1873. X    while( !st ) {
  1874. X        /* debugprintf( 5,( "getline %d: %s\n", line_number, curline )); */
  1875. X        if( strchr( curline, '=' )) {
  1876. X            macrocount++;
  1877. X            process_macroline( curline );
  1878. X
  1879. X            st = getline( curline, Param.MaxLine, infile );
  1880. X        }
  1881. X        else if( isemptyline( curline )) {
  1882. X            st = getline( curline, Param.MaxLine, infile );
  1883. X        }
  1884. X        else {
  1885. X            struct List cmdList;
  1886. X            struct target *targ = NULL;
  1887. X            struct command *cmd = NULL;
  1888. X            char *delim;
  1889. X
  1890. X            NewList( &cmdList );
  1891. X
  1892. X            targetcount++;
  1893. X            *commandline = (char)0;
  1894. X
  1895. X            delim = find_token( curline + 1, ':' );
  1896. X            if( delim ) {
  1897. X                if( delim = find_token( delim + 1, ';' ) ) {
  1898. X                    *delim++ = (char)0;
  1899. X                    *commandline = '\t'; /* commandlines begin with a tab */
  1900. X                    strcpy( commandline + 1, delim );
  1901. X                }
  1902. X            }
  1903. X
  1904. X            if( st = ( *commandline ) ? 0 :
  1905. X                getline( commandline, Param.MaxLine, infile )) break;
  1906. X            while( !st ) {
  1907. X                if( *commandline != '\t' ) break;
  1908. X                debugprintf( 5,("tabline %d: %s\n",line_number, commandline));
  1909. X                delim = commandline;
  1910. X                while( isspace( *delim )) delim++;
  1911. X                if( *delim ) { /* line is not empty */
  1912. X                    if( cmd = new_command( delim ))
  1913. X                        AddTail( &cmdList, &cmd->node );
  1914. X                    else {
  1915. X                        printf( "Could not add command for target\n" ); 
  1916. X                        goto death;
  1917. X                    }
  1918. X                }
  1919. X                st = getline( commandline, Param.MaxLine, infile );
  1920. X            } /* while */
  1921. X
  1922. X            debugprintf( 4, ("targetline %d is %s\n", line_number, curline));
  1923. X            targ = process_targetline( curline, &cmdList, builtin_flag );
  1924. X            if( !targ ) {
  1925. X                logprintf( "Error in Makefile before line %d: %s\n",
  1926. X                    line_number, curline );
  1927. X                goto death;
  1928. X            }
  1929. X
  1930. X            strcpy( curline, commandline );
  1931. X        } /* else */
  1932. X    } /* while */
  1933. X
  1934. X    debugprintf( 2,( "targetcount = %d\nmacrocount = %d\n", targetcount,
  1935. X        macrocount ));
  1936. X
  1937. X    if( Param.debug && Param.verbosity >= 5 ) {
  1938. X        dump_all();
  1939. X    }
  1940. X
  1941. X    if( get_directive_state()) {
  1942. X        logfile( "Missing endif directive in conditional\n" );
  1943. X        goto death;
  1944. X    }
  1945. X
  1946. X    free( commandline );
  1947. X    free( curline );
  1948. X    fclose( infile );
  1949. X    return( 0 );
  1950. Xdeath:
  1951. X    if( commandline ) free( commandline );
  1952. X    if( curline ) free( curline );
  1953. X    if( infile ) fclose( infile );
  1954. X    return( 1 );
  1955. X}
  1956. END_OF_FILE
  1957. if test 8514 -ne `wc -c <'read.c'`; then
  1958.     echo shar: \"'read.c'\" unpacked with wrong size!
  1959. fi
  1960. # end of 'read.c'
  1961. fi
  1962. echo shar: End of archive 2 \(of 3\).
  1963. cp /dev/null ark2isdone
  1964. MISSING=""
  1965. for I in 1 2 3 ; do
  1966.     if test ! -f ark${I}isdone ; then
  1967.     MISSING="${MISSING} ${I}"
  1968.     fi
  1969. done
  1970. if test "${MISSING}" = "" ; then
  1971.     echo You have unpacked all 3 archives.
  1972.     rm -f ark[1-9]isdone
  1973. else
  1974.     echo You still need to unpack the following archives:
  1975.     echo "        " ${MISSING}
  1976. fi
  1977. ##  End of shell archive.
  1978. exit 0
  1979. -- 
  1980. Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
  1981. Mail comments to the moderator at <amiga-request@uunet.uu.net>.
  1982. Post requests for sources, and general discussion to comp.sys.amiga.misc.
  1983.